﻿using System.ComponentModel.DataAnnotations;

// This namespace holds indicators in this folder and is required. Do not change it.
namespace uTrade.Core
{
    /// <summary>
    /// Chaikin Money Flow.
    /// </summary>
    public class ChaikinMoneyFlow : Indicator
    {
        private DataSeries moneyFlow;
        private SUM sumMoneyFlow;
        private SUM sumVolume;

        internal DataSeries High, Low, Volume;
        private DataSeries Close;

        protected override void Init()
        {
            Close = Input;

            moneyFlow = new DataSeries(this.Input);
            sumMoneyFlow = SUM(moneyFlow, Period);
            sumVolume = SUM(Volume, Period);
        }

        protected override void OnBarUpdate()
        {
            double close0 = Close[0];
            double low0 = Low[0];
            double high0 = High[0];

            moneyFlow[0] = Volume[0] * ((close0 - low0) - (high0 - close0)) / ((high0 - low0).ApproxCompare(0) == 0 ? 1 : (high0 - low0));
            Value[0] = 100 * sumMoneyFlow[0] / sumVolume[0];
        }

        #region Properties

        [Range(1, int.MaxValue)]
        [Parameter("Period", "Parameters")]
        public int Period { get; set; }

        #endregion Properties
    }

    #region generated code. Neither change nor remove.

    public partial class Indicator
    {
        private ChaikinMoneyFlow[] cacheChaikinMoneyFlow;

        public ChaikinMoneyFlow ChaikinMoneyFlow(DataSeries high, DataSeries low, DataSeries close, DataSeries volume, int period)
        {
            var cat = cacheChaikinMoneyFlow;
            if (cacheChaikinMoneyFlow != null)
                for (int idx = 0; idx < cacheChaikinMoneyFlow.Length; idx++)
                    if (cacheChaikinMoneyFlow[idx] != null && cacheChaikinMoneyFlow[idx].Period == period && cat[idx].High == high && cat[idx].Low == low && cat[idx].Volume == volume && cacheChaikinMoneyFlow[idx].EqualsInput(close))
                        return cacheChaikinMoneyFlow[idx];
            return CacheIndicator<ChaikinMoneyFlow>(new ChaikinMoneyFlow() { Period = period, High = high, Low = low, Volume = volume, Input = close }, ref cacheChaikinMoneyFlow);
        }
    }

    public partial class Strategy
    {
        public ChaikinMoneyFlow ChaikinMoneyFlow(int period)
        {
            return ChaikinMoneyFlow(Datas[0], period);
        }

        public ChaikinMoneyFlow ChaikinMoneyFlow(TransDatas data, int period)
        {
            return Indicator.ChaikinMoneyFlow(data.High, data.Low, data.Close, data.Volume, period);
        }
    }
}

#endregion generated code. Neither change nor remove.